#pragma once
#include "sock.hpp"
#include <vector>
#include <functional>
#include <pthread.h>

namespace ns_tcp_server
{
    using func_t = std::function<void(int)>;

    class TcpServer;

    class ThreadData
    {
    public:
        ThreadData(int sock, TcpServer *server)
            : _sock(sock), _server(server) {}
        ~ThreadData() {}

    public:
        int _sock;
        TcpServer *_server;
    };

    class TcpServer
    {
    private:
        static void *ThreadRoutine(void *args)
        {
            pthread_detach(pthread_self());
            ThreadData *td = static_cast<ThreadData *>(args);
            td->_server->Excute(td->_sock);
            close(td->_sock);
            delete td;

            return nullptr;
        }

    public:
        TcpServer(const uint16_t &port, const std::string &ip = "0.0.0.0")
        {
            _listensock = _sock.Socket();
            _sock.Bind(_listensock, port, ip);
            _sock.Listen(_listensock);
        }

        void BindServer(func_t func)
        { // 绑定方法
            _func.push_back(func);
        }

        void Excute(int sock)
        { // 执行方法
            for (auto &f : _func)
            {
                f(sock);
            }
        }

        void Start()
        {
            while (true)
            {
                std::string clientip;
                uint16_t clientport;
                int sock = _sock.Accpet(_listensock,
                                        &clientip, &clientport);
                if (sock == -1)
                    continue;
                logMessage(NORMAL,
                           "create new line success,sock: %d\n", sock);

                pthread_t tid;
                ThreadData *td = new ThreadData(sock, this);
                pthread_create(&tid, nullptr,
                               ThreadRoutine, (void *)td);
            }
        }

        ~TcpServer()
        {
            if (_listensock >= 0)
                close(_listensock);
        }

    private:
        int _listensock;
        Sock _sock;
        std::vector<func_t> _func;
        // std::unorder_map<func_t> f_map;
    };
}